vlwkaos' digital garden

브라우저 Viewport Interop 2022

개요

  • 현재 Viewport 웹 명세 관련 정의 및 설명 살펴보기
  • 현재 Viewport 웹 명세의 문제점
  • 어떤 조치가 이뤄지고 있는지와 그 대안

Viewport 용어 및 개념 정리

The Viewport

  • 유저가 문서와 상호작용할 수 있도록 문서가 보여지는 영역
  • 클래식 스크롤바(스크롤바가 오버레이되지 않는 경우)를 제외한 화면상 보이는 영역
  • 문서의 크기보다 Viewport가 작을 경우 스크롤을 지원해야한다.
imageimage
  • 지금은 Viewport의 종류가 많아져서 그냥 The Viewport라고 하는 것이 무엇인지 모호해졌다.
  • 예전의 The Viewport는 The Layout Viewport로 새로운 명칭이 붙게 되었다.

The Layout Viewport

  • position: fixed를 이용하여 뭔가를 배치했을 때 보여지는 영역
  • 스크롤시 따라다닌다.
  • 자료 원작자는 The Position Fixed Viewport라고 이름 지었었어야하는 것 아닌가하고 농담을 한다.

Containing Block

  • CSS에서는 DOM요소의 상자영역의 크기나 위치를 계산할 때 바깥 Containing Block의 테두리를 기준으로 한다.
  • 계산된 상자 영역은 다시금 해당 요소의 자식의 상자영역을 계산하는 기준 Containing Block이 된다.
  • 그렇다면 가장 처음에 배치될 때 기준이 되는 Containing Block은 뭘까?

아래 문서에서 각 요소의 Containing Block을 살펴보자

<!DOCTYPE html>
<html lang="en">
<body>
    <div class="parent">
        <div class="child"></div>
    </div>
</body>
</html>
  • <div class="child"></div>의 Containing Block은 <div class="parent">...</div>이다.
  • <div class="parent">...</div>의 Containing Block은 <body>...</body>이다.
  • <body>...</body>의 Containing Block은 rootElement 혹은 documentElement 혹은 <html>...</html>
  • 그럼 <html>...</html>은?

The Initial Containing Block(ICB)

  • ICB는 documentElement의 Containing Block이다.
  • 크기는 layout viewport의 너비와 높이로 설정되며, 위치는 좌,상(0,0)을 기준으로 배치된다.
  • 스크롤바 영역을 포함하지 않는다. 즉, 스크롤바가 생기면 크기가 줄어든다.
  • 데스크탑의 경우 ICB와 layout viewport는 서로 크기가 같다. 왜 같은 영역을 표현하는 개념이 두개일까?
  • 빨간색이 ICB, 파란색이 Layout Viewport이다.image
  • 문서를 아래로 스크롤 하는 경우,
    • ICB는 0,0에 고정되어있기 때문에 보여지는 영역 밖에 위치하게된다.
    • Layout Viewport는 따라온다.
  • ICB의 크기를 알고 싶으면 어떤 API를 사용해야할까?
    • document.documentElement.clientWidth / clientHeight 를 이용해야한다.
    • getBoundingClientRect() 는 containing block의 스타일이 적용 후 계산된 값이라서 width/height에 100% 값이 없으면 제대로 나오지 않는다.
    • window.width / height는 어떤 브라우저에서는 pinch zoom 하면 값이 바뀐다.

Viewport units

  • CSS에서 v* 는 ICB를 기준으로 한 Viewport의 비율 크기 단위이다.
  • vw, vh, vi, vb, vmin, vmax 가 있다.
  • 수직 스크롤바가 있을 때 width: 100vw 를 주면 수평 스크롤이 생긴다.
  • 스펙에 vw계산시 scrollbar는 없다고 가정하기 때문이다.
  • 개발자들이 화났다
image

Pinch-zoom 할 때 ICB, Layout Viewport

  • 아래와 같은 상태에서image
  • 아래로 스크롤을 했다고 가정하자.image
  • 빨간 영역은 ICB,
  • 파란 영역은 Layout Viewport,
  • 노란 점선은 우리에게 보여지는 영역(Visual Viewport)이라 하자
  • Pinch zoom-in을 하면 아래와 같은 상태일 것이다.image
  • Visual Viewport는 Layout Viewport안에 담긴다.
  • Zoom상태에서 스크롤 했을때 화면에 snap되는 경험을 해봤을 것이다.
  • Visual Viewport가 Layout Viewport 바깥으로 가지 않으면 실제 윈도우 스크롤은 발생하지 않는다.
  • 즉, Visual Viewport는 자신만의 scale과 scroll 상태를 가진다.

Visual Viewport API

window.visualViewport 로 사용 가능하다.

  • width / height: Visual Viewport의 너비와 높이
  • offsetTop / offsetLeft: Visual Viewport에서 Layout Viewport까지의 거리 (좌, 상 기준)
  • pageTop / pageLeft: Visual Viewport에서 ICB까지의 거리 (좌, 상 기준)
  • scale: 확대 축소 비율

mobile에선 어떨까?

  • 아래 브라우저(user-agent)의 Viewport는 어떻게 될까? (사파리, 크롬, 파이어폭스)

    image
  • Layout Viewport

    image
  • ICB

    image
  • Visual Viewport

    image
  • 그런데 만약 페이지가 위 아래로 길 때 아래로 스크롤하면 어떻게 될까?

    image
  • 이런식으로 상단 하단의 UI가 감춰지게 된다.

  • UI가 나타나고 감춰지는 방식은 브라우저마다 다르다.

    • 제스쳐가 끝나고
    • 리사이즈시
    • 스크롤시
    • 인터벌
  • 이때 Layout Viewport, ICB, Visual Viewport 영역은 어떻게 될까?

  • Layout Viewport

    imageimage
  • ICB는 초기 값이기 때문에 위치도 고정이고 크기도 바뀌지 않는다.

    imageimage
  • Visual Viewport는 UI가 사라진 영역만큼 확장된다.

    imageimage

The Large, Small and Dynamic Viewport

  • 그렇다면 vh 값은 어떻게 되나?image
  • 아까 분명 viewport unit은 ICB를 기준으로 한다고 했는데 왜 이렇지?
  • 모바일 사파리가 먼저 저렇게 했고 결국엔 모두 저렇게 통일하게 되었다.
  • vh는 툴바를 없는 것으로 가정한 크기로 측정
  • 그래서 스크롤을 내려서 UI가 사라지면 딱 맞게 된다.
  • 그렇다면 모바일의 경우 viewport가 사실상 두종류이다.
  • The Small Viewport: dynamic user agent interfaces(브라우저 UI) 가 보일 때 = ICB
    • sv*: svh, svw, svmin, svmax, svi, svb
  • The Large Viewport: 브라우저 UI 숨겨졌을 때 = ICB + 브라우저 UI 크기
    - `lv*`: `lvh, lvw, lvmin, lvmax, lvi, lvb`
    
    image
  • Dynamic Viewport: dv* 값이 언제 적용되는지는 브라우저가 UI를 어떤 메커니즘으로 숨기고 보여지냐에 따라 다름
    • dvh, dvw, dvmin, dvmax, dvi, dvb
  • 지금 chroimium은 feature flag로 사용 가능하고 파이어폭스와 사파리는 지원함

Resize Behavior

  • 여기부터 고통이 시작된다.
  • 아래는 ICB다.image
  • 가상키보드가 등장하면?image
  • 사파리를 제외하고 ICB가 변경된다. 초기값이니까 바뀌면 안되지 않나 싶으나... 현 상황은 이렇다.image
  • 이 자료를 만든 사람도 초기값이기 때문에 변하지 않는게 좋지 않을까라고 의견을 제시한다.image
  • 위처럼 ICB 크기는 Viewport unit에도 영향을 끼친다.
  • 때문에 Chromium에선 논의가 더 필요하다 보고 아직 새로운 Viewport Unit을 제공하지 않는다.
  • Layout Viewport를 살펴보면 상황이 비슷하다.image
  • position: fixed 요소의 위치가 어떻게 되는지 보자.
  • 어떤게 더 나을까? 두 방식 모두 사용처가 있어 중립의 입장을 취한다.
    • 만약 floating button을 만들고 싶다. 그러면 오른쪽과 같이 키패드가 올라오면서 키패드 위 영역부터 버튼이 표시되길 원할 것이다.
    • 만약 nav bar을 만들고 싶다. 그러면 왼쪽 처럼 키패드가 오버레이 되길 원할 것이다.

Virtual Keyboard API

  • 현재 Chroium만 지원한다.
  • 다른 vendor는 API에 동의하지 않았다.
    • 예를 들어 하나 말해보자면 키보드 숨김/보임을 API로 할 수 있다는 스펙에 동의하지 않았다.
  • API 예시를 하나 살펴보자
if ("virtualKeyboard" in navigator) {
    const vk = navigator.virtualKeyboard;

    vk.overlaysContent = true;
    
    vk.addEventListener('geometrychange', () => {
        console.log(vk.boundingRect);
    });
}
  • overlaysContent: 가상키보드가 보일 때 ICB와 Layout Viewport를 Resize하지 않음.
    • 아직 자바스크립트로만 이 기능을 활성화할 수 있다. 그래서 이슈를 제의한 상태이다.
  • geometrychange: 가상키보드 변형시 호출되는 이벤트
  • css에서 가상키보드 높이 값을 env(keyoard-inset-height)로 사용 가능

이런식으로 작동하면 좋겠다(행복회로)

  • 여기부터는 Bramus가 원하는 바
  • 문제1: 자바스크립트를 쓰지않고 처음부터 동작을 정의하면 좋겠다. image
  • 아래 처럼 메타 태그가 적절할 듯
<meta name="viewport" content="width=device-width, initial-scale=1.0, virtual-keyboard=overlays-content"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, virtual-keyboard=resize-layout"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, virtual-keyboard=resize-visual"/>
  • 혹은
<meta name="virtual-keyboard" content="overlays-content"/>
<meta name="virtual-keyboard" content="resize-layout"/>
<meta name="virtual-keyboard" content="resize-visual"/>
  • 개발자가 원하는 방식을 정의할 수 있는 방향이면 좋을 것 같다.
  • 이 스펙은 지원되는 건 아니고 일단은 그냥 Bramus 개인적인 바람이다.
  • 문제2: Layout Viewport크기가 그대로인 iOS 사파리 동작 방식에서 가상키보드 위쪽에 뭔가 위치하게 하고 싶다면?image
  • position: fixed / {viewport} 어떤 Viewport를 기준으로 fixed 할것인지 정할 수 있게 하면 어떨까? 라는 의견.
  • 아직 논의 중 https://github.com/w3c/csswg-drafts/issues/7475
    • 각 상황별 데모도 확인할 수 있다.

Viewport investigation effort

Credits

Referred in

브라우저 Viewport Interop 2022